home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------
- SPClock
- Version 2.1
-
- A simple sprite based clock that will stay in the upper left corner
- no matter which screen you switch to or where your screen scrolls
- (in WB2.0).
-
- Copyright (C) 1991, Mark Waggoner
- Permission is granted to distribute this as long as no charge beyond a
- reasonable media charge is required. Reasonable shall be defined to
- be the amount that Fred Fish charges or last charged for a disk of
- software.
-
- You will probably want tabs set to 4 when editing this file
-
- Compiles with Manx C, 5.2a
-
- Note that this program uses special startup code found in start.a68
- ------------------------------------------------------------------------*/
- #include <functions.h>
- #include <string.h>
- #include <stdlib.h>
- #include <graphics/gfxbase.h>
- #include <graphics/view.h>
- #include <graphics/sprite.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <exec/ports.h>
- #include <exec/tasks.h>
- #include <workbench/workbench.h>
- #include <workbench/startup.h>
- #include <workbench/icon.h>
- #ifndef SUPERHIRES
- #define SUPERHIRES 0x0020
- #endif
-
- /* The sprite height */
- #define SPHEIGHT 10
-
- /* Library Base Pointers */
- void *SysBase = NULL;
- struct GfxBase *GfxBase = NULL;
- struct IntuitionBase *IntuitionBase = NULL;
- void *DOSBase = NULL;
- void *IconBase = NULL;
-
- /* start.a68 saves the original stack pointer in _savsp */
- long _savsp;
-
- /* The workbench startup message */
- struct WBStartup *WBenchMsg = NULL;
-
- /* Option keywords */
- static char KWcolor1a[] = "COLOR1";
- static char KWcolor1b[] = "COLOR";
- static char KWcolor2a[] = "COLOR2";
- static char KWcolor2b[] = "SHADOW";
- static char KWcolor3a[] = "COLOR3";
- static char KWleft[] = "LEFT";
- static char KWtop[] = "TOP";
- static char KW24Hour[] = "24HOUR";
- static char KWNoBlink[] = "NOBLINK";
- static char KWQuit[] = "QUIT";
- static char KWStart[] = "START";
-
- /* a smaller (but probably slower) isspace than aztec's */
- #define isspace(c) (c == ' ' || c == '\t' | c == '\n')
-
- /* The colors to use */
- static long color1[3] = {15, 0, 0};
- static long color2[3] = { 0, 0, 0};
- static long color3[3] = { 0,15, 0};
-
- /* The clock position */
- static long ClockX = -1,
- ClockY = -1;
-
- /* Switch options: */
- static UBYTE Hours24 = 0;
- static UBYTE Blink = 1;
- static UBYTE StartOnly = 0;
-
- /* The images are stored here */
- static UWORD hourimage[SPHEIGHT+2][2];
- static UWORD minuteimage[SPHEIGHT+2][2];
-
- /* This data was generated from the "nums" file using nums2c.rexx
- The nums are copied into the images as appropriate */
- static UBYTE nums[13][2][10] = {
- { {0x3E,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3E,0x00},
- {0x00,0x1C,0x84,0x84,0x84,0x84,0x84,0x84,0xC0,0x7C} }, /* 0 */
- { {0x0C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x00},
- {0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x18} }, /* 1 */
- { {0x3E,0x63,0x03,0x03,0x0C,0x30,0x60,0x60,0x7F,0x00},
- {0x00,0x1C,0xC4,0x04,0x02,0x08,0x00,0x80,0x80,0xFE} }, /* 2 */
- { {0x3E,0x63,0x03,0x03,0x0E,0x03,0x03,0x63,0x3E,0x00},
- {0x00,0x1C,0xC4,0x04,0x00,0x1C,0x04,0x04,0xC0,0x7C} }, /* 3 */
- { {0x06,0x0E,0x16,0x26,0x46,0x7F,0x06,0x06,0x06,0x00},
- {0x00,0x00,0x08,0x08,0x08,0x80,0xF8,0x08,0x08,0x0C} }, /* 4 */
- { {0x7F,0x60,0x60,0x60,0x7E,0x03,0x03,0x63,0x3E,0x00},
- {0x00,0x9E,0x80,0x80,0x80,0xFC,0x04,0x04,0xC0,0x7C} }, /* 5 */
- { {0x3E,0x63,0x60,0x60,0x7E,0x63,0x63,0x63,0x3E,0x00},
- {0x00,0x1C,0x86,0x80,0x80,0x9C,0x84,0x84,0x40,0x7C} }, /* 6 */
- { {0x7F,0x03,0x03,0x06,0x0C,0x18,0x18,0x18,0x18,0x00},
- {0x00,0xFC,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x30} }, /* 7 */
- { {0x3E,0x63,0x63,0x63,0x3E,0x63,0x63,0x63,0x3E,0x00},
- {0x00,0x1C,0x84,0x84,0xC0,0x1C,0x84,0x84,0xC0,0x7C} }, /* 8 */
- { {0x3E,0x63,0x63,0x63,0x3F,0x03,0x03,0x63,0x3E,0x00},
- {0x00,0x1C,0x84,0x84,0xC0,0x7C,0x04,0x84,0xC0,0x7C} }, /* 9 */
- { {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} }, /* space */
- { {0x06,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x00},
- {0x00,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x08,0x0C} }, /* small 1 */
- { {0x06,0x09,0x01,0x01,0x02,0x04,0x08,0x08,0x0F,0x00},
- {0x00,0x06,0x1A,0x02,0x00,0x00,0x00,0x10,0x10,0x1E} }, /* small 2 */
- };
-
- /* Message port and name used to indicate we are running */
- struct MsgPort *SPPort = NULL;
- static char portname[] = "SPClock";
-
- /* The sprites that we allocate */
- UWORD minute_spnum = -1,hour_spnum = -1;
- struct SimpleSprite hour_sprite,minute_sprite;
-
- /*-------------------------------------------------------------------
- Exit the program, freeing up global resources
- -------------------------------------------------------------------*/
- void
- exit(int code)
- {
- long ret = code;
-
- if (minute_spnum != -1)
- FreeSprite(minute_spnum);
- if (hour_spnum != -1)
- FreeSprite(hour_spnum);
-
- if (SPPort)
- DeletePort(SPPort);
-
- if (GfxBase)
- CloseLibrary((struct Library *) GfxBase);
- if (IntuitionBase)
- CloseLibrary((struct Library *) IntuitionBase);
- if (DOSBase)
- CloseLibrary((struct Library *) DOSBase);
-
- if (WBenchMsg) {
- Forbid();
- ReplyMsg((struct Message *)WBenchMsg);
- }
-
- /* Get the original stack pointer back and return */
- {
- #asm
- move.l %%ret,d0 ;pick up return exit code
- move.l __savsp#,sp ;get back original stack pointer
- rts ;and exit
- #endasm
- }
- }
-
- /*-------------------------------------------------------------------
- See if SPClock is already running and signal it to stop
- -------------------------------------------------------------------*/
- void
- KillIfRunning(void) {
- struct MsgPort *oldport;
-
- /* Check if we are already running */
- Forbid();
- if (oldport = FindPort(portname))
- Signal(oldport->mp_SigTask,SIGBREAKF_CTRL_C);
- Permit();
- return;
- }
-
- /*-------------------------------------------------------------------
- See if we are already running by looking for a message port
- named "SPClock". If so, signal that process to stop.
- If we signal another process to stop or can't open the message
- port, we return an error code and the main program exits.
- -------------------------------------------------------------------*/
- int
- CheckIfRunning(void) {
- struct MsgPort *oldport;
- int error = 1;
-
- /* Check if we are already running */
- Forbid();
- if (oldport = FindPort(portname)) {
- if (!StartOnly)
- Signal(oldport->mp_SigTask,SIGBREAKF_CTRL_C);
- }
- else /* port doesn't exist, so add it and continue */
- if (SPPort = CreatePort(portname,0)) error = 0;
- Permit();
- return(error);
- }
-
- /*-------------------------------------------------------------------
- Open the libraries that we will be using
- -------------------------------------------------------------------*/
- int
- OpenLibraries(void) {
- register int error = 1;
-
- /* Open up the libraries we need (look at all those evil gotos!) */
- if (
- ((DOSBase = OpenLibrary("dos.library",0L)) != NULL) &&
- ((IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library",0L)) != NULL) &&
- ((GfxBase = (struct GfxBase *)
- OpenLibrary("graphics.library",0L)) != NULL)
- )
- error = 0;
- return(error);
- }
-
- /*-------------------------------------------------------------------
- Set the colors of the currently active viewport.
- This may make a mess of some screens.
- If so, and it bothers you, find a better algorithm
- -------------------------------------------------------------------*/
- void
- SetSpriteColors(void) {
- int color_reg1,color_reg2;
- struct ViewPort *vp;
- WORD vp_max_pen;
-
- /* base color register numbers */
- color_reg1 = ((hour_spnum & 0x06)*2)+16;
- color_reg2 = ((minute_spnum & 0x06)*2)+16;
-
- vp = GfxBase->ActiView->ViewPort;
- vp_max_pen = 1 << vp->RasInfo->BitMap->Depth;
-
- if ((color_reg1 > 16) && (color_reg1 > vp_max_pen)) {
- SetRGB4(vp,color_reg1+1,color1[0],color1[1],color1[2]);
- SetRGB4(vp,color_reg1+2,color2[0],color2[1],color2[2]);
- SetRGB4(vp,color_reg1+3,color3[0],color3[1],color3[2]);
- }
- if ((color_reg2 != color_reg1) && (color_reg2 > vp_max_pen)) {
- SetRGB4(vp,color_reg2+1,color1[0],color1[1],color1[2]);
- SetRGB4(vp,color_reg2+2,color2[0],color2[1],color2[2]);
- SetRGB4(vp,color_reg2+3,color3[0],color3[1],color3[2]);
- }
- }
-
- /*-------------------------------------------------------------------
- Initialize the sprites
- -------------------------------------------------------------------*/
- int
- InitSprites(void) {
- int i;
-
- /* Clear the sprite images */
- for(i=0;i<SPHEIGHT+2;i++)
- hourimage[i][0] = hourimage[i][1] =
- minuteimage[i][0] = minuteimage[i][1] = 0;
-
- /* Try to get sprites 2 and 3, otherwise, take whatever is available */
- hour_spnum = GetSprite(&hour_sprite,2L);
- if (hour_spnum == -1) {
- hour_spnum = GetSprite(&hour_sprite,-1L);
- if (hour_spnum == -1)
- return(1);
- }
- minute_spnum = GetSprite(&minute_sprite,3L);
- if (minute_spnum == -1) {
- minute_spnum = GetSprite(&minute_sprite,-1L);
- if (minute_spnum == -1)
- return(1);
- }
- SetSpriteColors();
- return(0);
- }
-
- /*-------------------------------------------------------------------
- Skip past the next space delimited token in a string
- -------------------------------------------------------------------*/
- char *
- SkipToken(char *s) {
- while(*s && isspace(*s)) s++;
- while(*s && !isspace(*s)) s++;
- return(s);
- }
-
- /*-------------------------------------------------------------------
- Check an option name for CLI parsing
- -------------------------------------------------------------------*/
- char *
- CheckOption(char *s,char *opt) {
- int l,m;
- char *t;
-
- l = strlen(opt);
-
- /* Find the length of the next word */
- m = 0; t = s;
- while(*t && !isspace(*t) && *t != '=') { t++; m++; }
-
- if (m!=l)
- s = NULL;
- else
- if (strncmp(s,opt,l))
- s = NULL;
- else {
- s+=l;
- /* Skip past an equal sign */
- while(*s && isspace(*s)) s++;
- if (*s == '=') s++;
- }
- return(s);
- }
-
- /*-------------------------------------------------------------------
- Extract a color specification from an argument
- -------------------------------------------------------------------*/
- char *
- ExtractColor(char *s,long color[3]) {
- color[0]=atoi(s);
- s = SkipToken(s);
- color[1]=atoi(s);
- s = SkipToken(s);
- color[2]=atoi(s);
- s = SkipToken(s);
- return(s);
- }
-
- /*-------------------------------------------------------------------
- Parse workbench options
- -------------------------------------------------------------------*/
- void
- wb_parse(struct WBStartup *wbm)
- {
- char *tool;
- struct DiskObject *dob;
-
- CurrentDir(wbm->sm_ArgList->wa_Lock);
-
- if ((IconBase = OpenLibrary("icon.library", 0L)) == 0)
- return;
- if ((dob = GetDiskObject(wbm->sm_ArgList->wa_Name)) == 0)
- goto NoDiskObj;
-
- if (tool = FindToolType((UBYTE **)dob->do_ToolTypes, KWcolor1a))
- ExtractColor(tool,color1);
- if (tool = FindToolType((UBYTE **)dob->do_ToolTypes, KWcolor1b))
- ExtractColor(tool,color1);
- if (tool = FindToolType((UBYTE **)dob->do_ToolTypes, KWcolor2a))
- ExtractColor(tool,color2);
- if (tool = FindToolType((UBYTE **)dob->do_ToolTypes, KWcolor2b))
- ExtractColor(tool,color2);
- if (tool = FindToolType((UBYTE **)dob->do_ToolTypes, KWcolor3a))
- ExtractColor(tool,color3);
- if (tool = FindToolType((UBYTE **)dob->do_ToolTypes, KWtop))
- ClockY = atoi(tool);
- if (tool = FindToolType((UBYTE **)dob->do_ToolTypes, KWleft))
- ClockX = atoi(tool);
- if (tool = FindToolType((UBYTE **)dob->do_ToolTypes, KW24Hour))
- Hours24 = 1;
- if (tool = FindToolType((UBYTE **)dob->do_ToolTypes, KWNoBlink))
- Blink = 0;
-
- FreeDiskObject(dob);
- NoDiskObj:
- CloseLibrary(IconBase);
- IconBase = NULL;
- }
-
- /*-------------------------------------------------------------------
- I parse the cli parameters before they get to main()
- -------------------------------------------------------------------*/
- void
- cli_parse(long alen, register char *aptr)
- {
- char *s,*t;
-
- s = aptr;
-
- while(*s) {
- while(*s && isspace(*s)) s++;
- if ((t = CheckOption(s,KWcolor1a)) || (t = CheckOption(s,KWcolor1b)))
- s = ExtractColor(t,color1);
- else
- if ((t = CheckOption(s,KWcolor2a)) || (t = CheckOption(s,KWcolor2b)))
- s = ExtractColor(t,color2);
- else
- if ((t = CheckOption(s,KWcolor3a)))
- s = ExtractColor(t,color3);
- else
- if (t = CheckOption(s,KWtop)) {
- ClockY = atoi(t);
- s = SkipToken(t);
- }
- else
- if (t = CheckOption(s,KWleft)) {
- ClockX = atoi(t);
- s = SkipToken(t);
- }
- else
- if (t = CheckOption(s,KW24Hour)) {
- Hours24 = 1;
- s = t;
- }
- else
- if (t = CheckOption(s,KWNoBlink)) {
- Blink = 0;
- s = t;
- }
- else
- if (t = CheckOption(s,KWQuit)) {
- KillIfRunning();
- s = t;
- exit(0);
- }
- else
- if (t = CheckOption(s,KWStart)) {
- StartOnly = 1;
- s = t;
- exit(0);
- }
- else
- s = SkipToken(s);
- }
- }
-
- /*-------------------------------------------------------------------
- Here it is!! The main program! Note that this is NOT called
- like a normal C main(). This is more like the _main() routine.
- You may not use any unix style standard i/o, or malloc, or
- any floating point in this program!
- -------------------------------------------------------------------*/
- main(long alen,char *aptr) {
- register struct Process *pr;
- int i,o1,o2,o3,o4;
- UWORD maxx;
- ULONG sec,usec,lastsec = 0;
- UWORD hours,minutes,pm;
- ULONG line;
-
- if (OpenLibraries()) exit(103); /* Open up the libraries */
-
- /* Figure out if we came from workbench or a CLI and process the
- arguments accordingly */
- pr = (struct Process *)FindTask(0L);
- if (pr->pr_CLI)
- cli_parse(alen, aptr);
- else {
- WaitPort(&pr->pr_MsgPort);
- WBenchMsg = (struct WBStartup *)GetMsg(&pr->pr_MsgPort);
-
- if (WBenchMsg->sm_ArgList)
- wb_parse(WBenchMsg);
- }
-
- /* See if we are already running, kill other process and exit if so */
- if (CheckIfRunning())
- exit(0);
-
- /* Initialize the sprites. Exit if unable to do so */
- if (InitSprites())
- exit(105);
-
- /* If no position specified, position the sprite near the right
- side, but not so it overlaps the usual screen gadgets */
- /* Can you suggest a better way to do this? */
- maxx = GfxBase->ActiView->ViewPort->DWidth;
- if (GfxBase->ActiView->ViewPort->Modes & HIRES) maxx *= 2;
-
- if (ClockX < 0) ClockX = maxx - 48;
- if (ClockY < 0) ClockY = 0;
- hour_sprite.x = ClockX;
- hour_sprite.y = ClockY;
- hour_sprite.height = SPHEIGHT;
-
- minute_sprite.x = ClockX+16;
- if (GfxBase->ActiView->Modes & SUPERHIRES)
- minute_sprite.x = ClockX+8;
- minute_sprite.y = ClockY;
- minute_sprite.height = SPHEIGHT;
-
- /* Keep running until we get a BREAK signal */
- while (!(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)) {
- /* Find out what time it is */
- CurrentTime(&sec,&usec);
- sec = sec/60; /* sec is now minutes */
- if (sec != lastsec) { /* Only update if the time has changed */
-
- /* Calculate the hours and minutes. I keep 12 hour time! */
- lastsec = sec;
- minutes = sec % 60;
- sec = sec/60;
- hours = sec%24;
- pm = 0;
- if (hours*60+minutes > 720) pm = 1;
- if (!Hours24) {
- if (hours > 12) hours -= 12;
- if (hours == 0) hours = 12;
- }
-
- o1 = hours/10+10;
- if (o1 > 12) o1 = 10;
- o2 = hours%10;
- o3 = minutes/10;
- o4 = minutes%10;
- for(i=0;i<SPHEIGHT;i++) {
- line = (((USHORT) nums[o1][0][i]) << 27) |
- (((USHORT) nums[o2][0][i]) << 19) |
- (((USHORT) nums[o3][0][i]) << 9) |
- (((USHORT) nums[o4][0][i]) << 1);
-
- hourimage[i+1][0] = (line & 0xFFFF0000) >> 16;
- minuteimage[i+1][0] = (line & 0x0000FFFF);
-
- line = (((USHORT) nums[o1][1][i]) << 27) |
- (((USHORT) nums[o2][1][i]) << 19) |
- (((USHORT) nums[o3][1][i]) << 9) |
- (((USHORT) nums[o4][1][i]) << 1);
- hourimage[i+1][1] = (line & 0xFFFF0000) >> 16;
- minuteimage[i+1][1] = (line & 0x0000FFFF);
- }
- /* Make the Colon and AM/PM indicator */
- hourimage[3][0] |= 0x0002;
- hourimage[7][0] |= 0x0002;
- hourimage[4][1] |= 0x0004;
- hourimage[8][1] |= 0x0004;
-
- if (pm && !Hours24) {
- hourimage[5][0] |= 0x0002;
- hourimage[5][1] |= 0x0002;
- hourimage[6][1] |= 0x0004;
- }
- }
-
- /* Make the blinking dots */
- if (Blink) {
- hourimage[3][0] ^= 0x0002;
- hourimage[7][0] ^= 0x0002;
- hourimage[4][1] ^= 0x0004;
- hourimage[8][1] ^= 0x0004;
- }
-
- /* Make sure this viewport has my colors set. I would like
- to not do this every time, but I'm not sure how to check
- if another screen has moved to the front */
- SetSpriteColors();
-
- /* Update the image */
- ChangeSprite(NULL,&hour_sprite,(PLANEPTR) hourimage);
- ChangeSprite(NULL,&minute_sprite,(PLANEPTR) minuteimage);
-
- /* Wait for 1 second */
- Delay(50);
- }
-
- exit(0);
- }
-